import os

#---------------------------------- TOOL PATH ----------------------------------
mingw_gcc_path = r"D:/Software/mingw64/bin/gcc.exe"
mingw_gpp_path = r"D:/Software/mingw64/bin/g++.exe"
qt_gcc_path = r"D:/Software/Qt/Qt5.14.2/Tools/mingw730_64/bin/gcc.exe"
qt_gpp_path = r"D:/Software/Qt/Qt5.14.2/Tools/mingw730_64/bin/g++.exe"
arm_gcc_path = r"D:/Software/Arm GNU Toolchain arm-none-eabi/10 2021.10/bin/arm-none-eabi-gcc.exe"
arm_gpp_path = r"D:/Software/Arm GNU Toolchain arm-none-eabi/10 2021.10/bin/arm-none-eabi-g++.exe"
cmake_path = r"D:/Software/Cmake/bin/cmake.exe"
ninja_path = r"D:/Software/ninja-win/ninja.exe"
openocd_path = r"D:/Software/OpenOCD/bin/openocd.exe"
openocd_scripts_path = r"D:/Software/OpenOCD/share/openocd/scripts"

#---------------------------------- CLAND 文件模板 ----------------------------------
clangd_setting = r"""
        "--log=verbose",
        "--pretty",
        "--background-index",
        "-j=12",
        "--pch-storage=disk",
        "--completion-style=detailed",
        "--all-scopes-completion",
        "--function-arg-placeholders=false",
        "--header-insertion=iwyu",
        "--header-insertion-decorators",
        "--clang-tidy",
        "--clang-tidy-checks=cppcoreguidelines-*,performance-*,bugprone-*,portability-*,modernize-*,google-*",
        "--compile-commands-dir=${workspaceFolder}/build",
        "--cross-file-rename",
        "--enable-config"
"""

clangd_setting_arm = fr"""
CompileFlags:
    Remove: [
        "-mcpu=cortex-m3",
    ]
    Compiler: {arm_gcc_path}
"""

#---------------------------------- TASK BUTTON 文件模板 ----------------------------------
task_buttons = r"""
{
    "buttons": [
      {
        "name": "                                                                                          NULL",
        "task": "",
        "icon": "",
        "tooltip": ""
      },
      {
        "name": "Configure",
        "task": "CMake Configure",
        "icon": "🛠️",
        "tooltip": "CMake Configure"
      },
      {
        "name": "Build",
        "task": "CMake Build",
        "icon": "🔨",
        "tooltip": "Build the project"
      },
      {
        "name": "Run",
        "task": "CMake Run",
        "icon": "▶️",
        "tooltip": "Run the project"
      },
      {
        "name": "Debug",
        "task": "Debug",
        "icon": "🐞",
        "tooltip": "Debug the project"
      }
    ]
}
"""

#---------------------------------- LAUNCH 文件模板 ----------------------------------
arm_launch = r"""
{
    "configurations": [
    {
        "cwd": "${workspaceFolder}/build",
        // 换成你的elf文件路径
        "executable": "xxx.elf",
        "name": "Debug with OpenOCD",
        "request": "launch",
        "type": "cortex-debug",
        "servertype": "openocd",
        "configFiles": [
            "interface/cmsis-dap.cfg",
            // 换成你的cfg文件路径
            "target/stm32f1x.cfg"
        ],
        "searchDir": [],
        "runToEntryPoint": "main",
        "showDevDebugOutput": "none",
        // 换成你的svd文件路径
        "svdFile": "STM32F103.svd"
    }
    ]
}
"""

gcc_launch = r"""
{
    "configurations": [
        {
            "type": "lldb",
            "request": "launch",
            "name": "Launch",
            // 换成你的exe文件路径
            "program": "xxx.exe",
            "args": [],
            "cwd": "${workspaceFolder}/build",
            "stopOnEntry": true
        }
    ]
}
"""

qt_launch = r"""
{
    "configurations": [
    {
        "type": "lldb",
        "request": "launch",
        "name": "Launch",
        // 换成你的exe文件路径
        "program": "xxx.exe",
        "args": [],
        "cwd": "${workspaceFolder}/build",
        "stopOnEntry": true,
        // 换成你的lldbinit文件路径
        "initCommands": [
            "command script import D:/Software/gdbPrettyPrinters/lldb/all.py",
        ]
    }
    ]
}
"""

#---------------------------------- LAUNCH 文件模板 ----------------------------------
def generate_settings_json(gcc_path, gpp_path):
    setting = fr"""
{{
    "clangd.arguments": [
        "--query-driver={gcc_path},{gpp_path}",
{clangd_setting}
    ]
}}
"""
    return setting

def generate_run(type, openocd_path, openocd_scripts_path):
    c_run = fr"""
            // 替换你的exe
            "command": "xxx.exe",
            "args": [
            ],
            "dependsOrder": "sequence",
"""

    arm_run = fr"""
            "command": "{openocd_path}",
            "args": [
                "-s", "{openocd_scripts_path}",
                // 换成你的cfg文件路径
                "-f", "xxx.cfg",
                "-c", "tcl_port disabled",
                "-c", "gdb_port disabled",
                "-c", "tcl_port disabled",
                // 换成你的elf文件路径
                "-c", "program \"xxx.elf\"",
                "-c", "reset",
                "-c", "shutdown"
            ],
"""
    if type == "c":
        return c_run
    else:
        return arm_run

def generate_tasks_json(type, cmake_path, ninja_path, openocd_path, openocd_scripts_path, gcc_path, gpp_path):
    
    cmake_run = generate_run(type, openocd_path, openocd_scripts_path)
    
    tasks = fr"""
{{
    "version": "2.0.0",
    "tasks": [
        {{
            "label": "CMake Configure",
            "type": "shell",
            "command": "{cmake_path}",
            "args": [
                "-DCMAKE_BUILD_TYPE=Debug",
                "-DCMAKE_MAKE_PROGRAM={ninja_path}",
                "-DCMAKE_C_COMPILER={gcc_path}",
                "-DCMAKE_CXX_COMPILER={gpp_path}",
                "-G", "Ninja",
                "-S", "${{workspaceFolder}}",
                "-B", "${{workspaceFolder}}/build",
                "-DCMAKE_C_FLAGS=-g -gdwarf-4",
                "-DCMAKE_CXX_FLAGS=-g -gdwarf-4"
            ],
            "dependsOrder": "sequence",
            "dependsOn": [
                "Clear Terminal"
            ]
        }},
        {{
            "label": "CMake Build",
            "type": "shell",
            "command": "{cmake_path}",
            "args": [
                "--build", "${{workspaceFolder}}/build",
                "--target", "${{workspaceFolderBasename}}",
                "-j", "16"
            ],
            "dependsOrder": "sequence",
            "dependsOn": [
                "Clear Terminal"
            ]
        }},
        {{
            "label": "CMake Run",
            "type": "shell",
{cmake_run}
            "dependsOn": [
                "CMake Build",
                "Clear Terminal"
            ]
        }},
        {{
            "label": "Debug",
            "type": "shell",
            "command": "Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.SendKeys]::SendWait('{{F5}}')",
            "dependsOrder": "sequence",
            "dependsOn": [
                "CMake Build",
                "Clear Terminal"
            ]
        }},
        {{
            "label": "Clear Terminal",
            "type": "shell",
            "command": "clear"
        }}
    ]
}}
"""
    return tasks

def vscode_init():
    if not os.path.exists(".vscode"):
        os.mkdir(".vscode")

    with open(".vscode/task-buttons.json", "w", encoding="utf-8") as f:
        f.write(task_buttons)

def creat_arm_vscode_file():
    setting = generate_settings_json(arm_gcc_path, 
                                     arm_gpp_path)
    with open(".vscode/settings.json", "w", encoding="utf-8") as f:
        f.write(setting)

    tasks = generate_tasks_json("arm", 
                                cmake_path, 
                                ninja_path, 
                                openocd_path, 
                                openocd_scripts_path,
                                arm_gcc_path, 
                                arm_gpp_path)
    with open(".vscode/tasks.json", "w", encoding="utf-8") as f:
        f.write(tasks)

    with open(".vscode/launch.json", "w", encoding="utf-8") as f:
        f.write(arm_launch)

    with open(".clangd", "w", encoding="utf-8") as f:
        f.write(clangd_setting_arm)

def creat_c_vscode_file():
    setting = generate_settings_json(mingw_gcc_path, 
                                     mingw_gpp_path)
    with open(".vscode/settings.json", "w", encoding="utf-8") as f:
        f.write(setting)

    tasks = generate_tasks_json("c", 
                                cmake_path, 
                                ninja_path, 
                                "", 
                                "",
                                mingw_gcc_path, 
                                mingw_gpp_path)
    with open(".vscode/tasks.json", "w", encoding="utf-8") as f:
        f.write(tasks)

    with open(".vscode/launch.json", "w", encoding="utf-8") as f:
        f.write(gcc_launch)

def creat_qt_vscode_file():
    setting = generate_settings_json(qt_gcc_path, 
                                     qt_gpp_path)
    with open(".vscode/settings.json", "w", encoding="utf-8") as f:
        f.write(setting)

    tasks = generate_tasks_json("c", 
                                cmake_path, 
                                ninja_path, 
                                openocd_path, 
                                openocd_scripts_path,
                                qt_gcc_path, 
                                qt_gpp_path)
    with open(".vscode/tasks.json", "w", encoding="utf-8") as f:
        f.write(tasks)

    with open(".vscode/launch.json", "w", encoding="utf-8") as f:
        f.write(qt_launch)

if __name__ == "__main__":

    type = input("请输入类型(c/arm/qt): ")

    if type not in ["c", "arm", "qt"]:
        print("输入错误")
        os._exit(0)

    try:
        vscode_init()
        if type == "c":
            creat_c_vscode_file()
        elif type == "arm":
            creat_arm_vscode_file()
        elif type == "qt":
            creat_qt_vscode_file()
        print("创建成功")
    except Exception as e:
        print(e)
        print("创建失败")
    os._exit(0)

    
